//
//  mb_SoundSystem.h
//  mbaudio
//
//  Created by avansc on 4/17/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef _MBAudio_h
#define _MBAudio_h

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif
    
    typedef struct ALCdevice_struct ALCdevice;
    typedef struct ALCcontext_struct ALCcontext;
    
    #define DEG2RAD(x) (0.0174532925 * (x))
    #define RAD2DEG(x) (57.295779578 * (x))
    
    ////////////// Hash Map ///////////////
    
    #define mb_value(h, x) ((h)->vals[x])
    
    typedef struct mb_pUIMap {
        uint32_t n_buckets, size, n_occupied, upper_bound;
        uint32_t *flags;
        const char **keys;
        unsigned int **vals;
    } mb_pUIMap_t;
    
    ////////////// Hash Map ///////////////
    
    ////////////// Sound Buffer ///////////////
    
    typedef unsigned int mb_SoundBuffer_t;
    
    typedef void (*fp_initSoundBufferMap)(void);
    typedef int (*fp_setSoundBufferMap)(const char*, mb_SoundBuffer_t*);
    typedef mb_SoundBuffer_t* (*fp_getSoundBufferMap)(const char*);
    typedef int (*fp_addSoundBuffer)(mb_SoundBuffer_t);
    typedef int (*fp_removeSoundBuffer)(mb_SoundBuffer_t);
    
    typedef struct mb_SoundBufferMap
    {
        int                     m_initialized;
        mb_pUIMap_t             *m_buffersMap;
        
        fp_initSoundBufferMap   init;
        fp_setSoundBufferMap    set;
        fp_getSoundBufferMap    get;
        
        fp_addSoundBuffer       add;
        fp_removeSoundBuffer    remove;
        
    } mb_SoundBufferMap_t;
    
    mb_SoundBufferMap_t *createSoundBufferMap(void);
    mb_SoundBufferMap_t *setActiveSoundBufferMap(mb_SoundBufferMap_t *map);
    
    ////////////// Sound Buffer ///////////////
    
    
    ////////////// Sound Source ///////////////
    
    typedef struct mb_SoundSource
    {
        unsigned int*   m_source;
        volatile int    m_done;
    } mb_SoundSource_t;
    
    typedef void (*fp_initSoundSourceMap)(void);
    typedef int (*fp_setSoundSourceMap)(const char*, unsigned int*);
    typedef unsigned int* (*fp_getSoundSourceMap)(const char*);
    typedef int (*fp_addSoundSource)(unsigned int);
    typedef int (*fp_removeSoundSource)(unsigned int);
    
    typedef struct mb_SoundSourceMap
    {
        int                     m_initialized;
        mb_pUIMap_t             *m_sourcesMap;
        
        fp_initSoundSourceMap   init;
        fp_setSoundSourceMap    set;
        fp_getSoundSourceMap    get;
        
        fp_addSoundSource       add;
        fp_removeSoundSource    remove;
        
    } mb_SoundSourceMap_t;
    
    mb_SoundSourceMap_t *createSoundSourceMap(void);
    mb_SoundSourceMap_t *setActiveSoundSourceMap(mb_SoundSourceMap_t *map);
    
    void mb_playSource(mb_SoundSource_t *source);
    int mb_isPlaying(mb_SoundSource_t *source);
    
    unsigned int *mb_genSource(int num);
    unsigned int *mb_genBuffer(int num);
    
    ////////////// Sound Source ///////////////
    
    
    ////////////// Sound Listener ///////////////
    
    typedef float mb_listenerPos[3];
    typedef float mb_listenerVel[3];
    typedef float mb_listenerOrientation[6];
    
    typedef void (*fp_initSoundListener)(void);
    
    typedef void (*fp_getListenerPosition)(mb_listenerPos*);
    typedef void (*fp_getListenerVelocity)(mb_listenerVel*);
    typedef void (*fp_getListenerOrientation)(mb_listenerOrientation*);
    
    typedef void (*fp_setListenerPosition)(mb_listenerPos);
    typedef void (*fp_setListenerVelocity)(mb_listenerVel);
    typedef void (*fp_setListenerOrientation)(mb_listenerOrientation);
    
    typedef struct mb_SoundListener
    {
        int                         m_initialized;
        
        fp_initSoundListener        init;
        fp_getListenerPosition      getPosition;
        fp_getListenerVelocity      getVelocity;
        fp_getListenerOrientation   getOrientation;
        
        fp_setListenerPosition      setPosition;
        fp_setListenerVelocity      setVelocity;
        fp_setListenerOrientation   setOrientation;
        
    } mb_SoundListener_t;
    
    mb_SoundListener_t *createSoundListener(void);
    mb_SoundListener_t *setActiveSoundListener(mb_SoundListener_t *listener);
    
    ////////////// Sound Listener ///////////////
    
    
    ////////////// Sound System ///////////////
    
    
    typedef int (*fp_initSoundSystem)();
    typedef mb_SoundBuffer_t* (*fp_loadSoundFile)(char*);
    
    typedef mb_SoundBuffer_t* (*fp_addSoundBufferFromFile)(char*, char*);
    typedef mb_SoundBuffer_t* (*fp_addSoundBufferFromMem)(char*, mb_SoundBuffer_t*);
    typedef mb_SoundSource_t (*fp_addSoundSource_t)(char*);
    typedef int (*fp_attachBufferToSource)(char*, char*);
    typedef int (*fp_attach)(mb_SoundBuffer_t*, mb_SoundSource_t*);
    
    typedef void (*fp_playSource)(char*);
    typedef int (*fp_createSource)(char*);
    typedef mb_SoundSource_t (*fp_getSource)(char*);
    
    typedef mb_SoundBuffer_t* (*fp_addSBuffer)(char*, char*);
    
    typedef struct mb_SoundSystem
    {
        ALCdevice*                  m_device;
        ALCcontext*                 m_context;
        int                         m_initialized;
        
        mb_SoundListener_t*         m_listener;
        
        mb_SoundSourceMap_t*        m_sourceMap;
        mb_SoundBufferMap_t*        m_bufferMap;
        
        fp_initSoundSystem          initSoundSystem;
        fp_loadSoundFile            loadSoundFile;
        fp_addSoundBufferFromFile   addSoundBufferFromFile;
        fp_addSoundBufferFromMem    addSoundBufferFromMem;
        fp_addSoundSource_t         addSoundSource;
        fp_attachBufferToSource     attachBufferToSource;
        fp_attach                   attach;
        fp_playSource               playSource;
        fp_createSource             createSource;
        fp_getSource                getSource;
        
    } mb_SoundSystem_t;
    
    mb_SoundSystem_t *createSoundSystem(void);
    mb_SoundSystem_t *setActiveSoundSystem(mb_SoundSystem_t *system);
    
    ////////////// Sound System ///////////////
    
#ifdef __cplusplus
}
#endif

#endif
